/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <csignal>
#include <thread>
#include <iostream>
#include <unistd.h>
#include <unordered_map>
#include "dal/identifier.h"
#include "dal/domain_participant.h"
#include "dal/subscriber.h"
#include "dal/topic.h"
#include "dal/config_loader.h"
#include "my_package/msg/all_type.hpp"

volatile sig_atomic_t g_signal_received = false;

void signal_handler(int signal)
{
    g_signal_received = true;
}

static void reg_sigs()
{
    std::signal(SIGINT, signal_handler);
    std::signal(SIGILL, signal_handler);
    std::signal(SIGABRT, signal_handler);
    std::signal(SIGSEGV, signal_handler);
    std::signal(SIGTERM, signal_handler);
    std::signal(SIGBUS, signal_handler);
}

void on_data_available_callback(dal_datareader_t* reader, void* data)
{
    dal_sample_info_t info;
    my_package::msg::AllType msg;

    if (dal_datareader_take_next_sample(reader, &msg, &info) == DAL_RETCODE_OK) {
        if (info.valid_data == 1) {
            std::cout << "[listener]: recv msg, i16: " << msg.i16 << ", str: " << msg.str
                      << ", unbound_u8_arr's size: " << msg.unbound_u8_arr.size() << std::endl;
        }
    } else {
        std::cout << "[listener]: recv msg failed" << std::endl;
    }
}

void on_subscription_matched_callback(dal_datareader_t* reader,
                                      dal_subscription_matched_status_t* status,
                                      void* data)
{
    std::cout << "[listener]: subscription matched callback, total_cnt = " << status->total_count
              << ", total_cnt change = " << status->total_count_change
              << ", curr_cnt = " << status->current_count
              << ", curr_cnt_change = " << status->current_count_change
              << ", last_pub_handle = " << status->last_publication_handle.segment_0_ << " "
              << status->last_publication_handle.segment_1_ << " "
              << status->last_publication_handle.segment_2_ << " "
              << status->last_publication_handle.segment_3_ << std::endl;
}

int main(int argc, char* argv[])
{
#if defined (__x86_64__)
    std::string prefix = "/opt/cyber/usr/bin/dal/TestCases/Helloworld/conf/";
#elif defined (__android_aarch64__)
    std::string prefix = "/vendor/etc/dal/conf/";
#else
    std::string prefix = "/usr/bin/autoplt/demos/bst-hanhai-dal-demo/HelloWorld/conf/";
#endif
    std::string fastdds_conf_path = prefix + "dal_fastdds_profiles.xml";
    std::string cyclonedds_conf_path = prefix + "dal_cyclonedds_config.xml";
    std::string rtidds_conf_path = prefix + "DAL_RTI_USER_QOS_PROFILES.xml";

    std::unordered_map<std::string, const char*> conf_file_path_map = {
        {DAL_FASTDDS_IDENTIFIER, fastdds_conf_path.c_str()},
        {DAL_CYCLONEDDS_IDENTIFIER, cyclonedds_conf_path.c_str()},
        {DAL_RTICONNEXTDDS_IDENTIFIER, rtidds_conf_path.c_str()}};

    reg_sigs();

    dal_load_config_from_path(conf_file_path_map.at(dal_get_identifier()), nullptr);
    // create participant
    dal_domain_participant_t* part = dal_create_domain_participant_with_profile(
        20, DAL_PARTICIPANT_QOS_DEFAULT, "dal_testcase_participant_profile", NULL, 0);

    // create subscriber
    dal_subscriber_t* sub = dal_domain_participant_create_subscriber_with_profile(
        part, DAL_SUBSCRIBER_QOS_DEFAULT, "dal_testcase_subscriber_profile", NULL, 0);

    // register type
    dal_type_support_t* ts =
        dal_create_type_support((void*)(my_package::msg::AllType::FullyQualifiedName()));
    dal_type_support_register_type(ts, part, dal_type_support_get_type_name(ts));

    // create topic
    dal_topic_t* topic =
        dal_domain_participant_create_topic_with_profile(part,
                                                         "HelloWorldTopic",
                                                         dal_type_support_get_type_name(ts),
                                                         DAL_TOPIC_QOS_DEFAULT,
                                                         "dal_testcase_topic_profile",
                                                         nullptr,
                                                         0);

    dal_datareader_listener_callbacks_t reader_callbacks;
    memset(&reader_callbacks, 0, sizeof(reader_callbacks));
    reader_callbacks.on_data_available = &on_data_available_callback;
    reader_callbacks.on_subscription_matched = &on_subscription_matched_callback;
    dal_datareader_listener_t* reader_listener = dal_create_datareader_listener(reader_callbacks);

    // create data reader
    dal_datareader_t* reader =
        dal_subscriber_create_datareader_with_profile(sub,
                                                      topic,
                                                      DAL_DATAREADER_QOS_DEFAULT,
                                                      "dal_testcase_datareader_profile",
                                                      reader_listener,
                                                      DAL_ANY_STATUS);

    while (!g_signal_received) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }

    dal_subscriber_delete_datareader(sub, reader);
    dal_delete_datareader_listener(reader_listener);
    dal_domain_participant_delete_topic(part, topic);
    dal_delete_type_support(ts);
    dal_domain_participant_delete_subscriber(part, sub);
    dal_delete_domain_participant(part);
}